//
//  ZNGRequestTool.m
//  开店通
//
//  Created by 张浩 on 15/9/29.
//  Copyright © 2015年 张浩. All rights reserved.
//

#import "ZNGRequestTool.h"
#import "ZNGAlertView.h"
#import "MBProgressHUD+ZNG.h"
#import "MJExtension.h"
#import "ZNGConstants.h"

typedef void (^FormDataBlock)(id <AFMultipartFormData> formData);
typedef void (^SuccessBlock)(NSURLSessionDataTask * task, id responseObject);
typedef void (^FailureBlock)(NSURLSessionDataTask * task, NSError * error);


@implementation ZNGRequestManager

static ZNGRequestManager *_instance;

SetHttpHeaderField _setHeader;

+ (void)setHeaderField:(SetHttpHeaderField)setHeader
{
    _setHeader = setHeader;
}

+ (instancetype)shareManager
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[ZNGRequestManager alloc] initWithBaseURL:nil];
        
        _instance.requestSerializer = [AFHTTPRequestSerializer serializer];
        _instance.responseSerializer = [AFHTTPResponseSerializer serializer];
        
        
        NSOperationQueue *operationQueue = _instance.operationQueue;
        [_instance.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
            switch (status) {
                case AFNetworkReachabilityStatusReachableViaWWAN:
                case AFNetworkReachabilityStatusReachableViaWiFi:
                    [operationQueue setSuspended:NO];
                    break;
                case AFNetworkReachabilityStatusNotReachable:
                default:
                    [MBProgressHUD showTextMessage:@"无网络"];
                    [operationQueue setSuspended:YES];
                    break;
            }
        }];
        
        [_instance.reachabilityManager startMonitoring];
        
        _instance.requestSerializer.timeoutInterval = 20;
    });
    if (_setHeader) {
        _setHeader(_instance);
    }

    return _instance;
}
@end


@interface ZNGRequestTool ()

@end

@implementation ZNGRequestTool
static BOOL _showMessage;

CustomSuccessAction _successAction;
MessageShowRuleBlock _ruleBlock;

+ (void)setSuccessAction:(CustomSuccessAction)successAction
{
    _successAction = successAction;
}

+ (void)setMessageShowRule:(MessageShowRuleBlock)ruleBlock
{
    _ruleBlock = ruleBlock;
}

+ (void)load
{
    _showMessage = NO;
    
    _successAction = ^(ZNGBaseRequestResult *result, BOOL needShowMessage){
        if (result.code == 20000) {
            ZNGAlertView *alertView = [[ZNGAlertView alloc] initWithTitle:@"提示" message:@"当前版本过低，请更新..." cancelButtonTitle:@"确定" otherButtonTitles: nil];
            [alertView showWithButtonClickAction:^(NSInteger index) {
                exit(0);
            }];
            return ;
        }
        // 非成功操作，提示用户消息
        if (result.code != 200 && needShowMessage) {
            [MBProgressHUD showTextMessage:result.message];
        }
        //     异地登录 直接返回上级界面
        if (result.code == 601) {
            return;
        }
    };
}

#pragma mark - 是否显示消息提示

+ (void)showMBProgressHUDWithParam:(NSDictionary *)param andUrl:(NSString *)url
{
    _showMessage = YES;
    if (_ruleBlock) {
        _showMessage = _ruleBlock(url, param);
    }
    else {
        if ([param.allKeys containsObject:@"page"]) {
            // 分页不做消息提醒
            _showMessage = NO;
        }
    }
}


+ (void)request:(NSString *)url method:(HTTPMethod)httpMethod param:(id)param resultClass:(Class)resultClass constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))formData successBlock:(void (^)(id result))success failure:(void (^)(NSError *error))failure
{
    NSDictionary *dictParam = [param mj_keyValues];
 
    SuccessBlock successBlock = ^(NSURLSessionDataTask *task, id responseObject) {
        [self successWithResponseObj:responseObject resultClass:resultClass andSuccessBlock:success];
    };
    
    FailureBlock failureBlock = ^(NSURLSessionDataTask *task, NSError *error) {
        [self failureWithError:error andFailureBlock:failure];
    };

    [self showMBProgressHUDWithParam:dictParam andUrl:url];
    
    if (_showMessage) {
        [MBProgressHUD showLoadingMessage:@"火速处理中..."];
    }
    
    ZNGRequestManager *manager = [ZNGRequestManager shareManager];
    
    if (httpMethod == HTTPMethodGET) {
        [manager GET:url parameters:dictParam success:successBlock failure:failureBlock];
    }
    else if (httpMethod == HTTPMethodPOST) {
        if (formData) {
            FormDataBlock formDataBlock = ^(id <AFMultipartFormData> data) {
                if (formData) {
                    formData(data);
                }
            };
            [manager POST:url parameters:dictParam constructingBodyWithBlock:formDataBlock success:successBlock failure:failureBlock];
        }
        else {
            [manager POST:url parameters:dictParam success:successBlock failure:failureBlock];
        }
    }
}

#pragma mark - 请求失败统一回调

+ (void)failureWithError:(NSError *)error andFailureBlock:(void (^)(NSError *))failure
{
    [MBProgressHUD hideHUD];
    [MBProgressHUD showTextMessage:@"网络异常"];
    ZNGLog(@"%@", error);
    if (failure) {
        failure(error);
    }
}

#pragma mark - 请求成功统一回调
+ (void)successWithResponseObj:(id)responseObj resultClass:(Class)resultClass andSuccessBlock:(void (^)(id responseObj))success
{
    [MBProgressHUD hideHUD];
    id response = [NSJSONSerialization JSONObjectWithData:responseObj options:NSJSONReadingAllowFragments error:nil];
    
    ZNGBaseRequestResult *result = (ZNGBaseRequestResult *)[resultClass mj_objectWithKeyValues:response];
    
    if (_successAction) {
        _successAction(result, _showMessage);
    }

    // 执行成功回调
    if (success) {
        success(result);
    }
}

+ (void)post:(NSString *)url param:(id)param successBlock:(void (^)(ZNGBaseRequestResult *result))success failure:(void (^)(NSError *error))failure
{
    [self request:url method:HTTPMethodPOST param:param resultClass:[ZNGBaseRequestResult class] constructingBodyWithBlock:nil successBlock:success failure:failure];
}
+ (void)get:(NSString *)url param:(id)param successBlock:(void (^)(ZNGBaseRequestResult *result))success failure:(void (^)(NSError *error))failure
{
    [self request:url method:HTTPMethodGET param:param resultClass:[ZNGBaseRequestResult class] constructingBodyWithBlock:nil successBlock:success failure:failure];
}


+ (void)post:(NSString *)url param:(id)param resultClass:(Class)resultClass successBlock:(void (^)(id result))success failure:(void (^)(NSError *error))failure
{
    [self request:url method:HTTPMethodPOST param:param resultClass:resultClass constructingBodyWithBlock:nil successBlock:success failure:failure];
}
+ (void)get:(NSString *)url param:(id)param resultClass:(Class)resultClass successBlock:(void (^)(id result))success failure:(void (^)(NSError *error))failure
{
    [self request:url method:HTTPMethodGET param:param resultClass:resultClass constructingBodyWithBlock:nil successBlock:success failure:failure];
}


+ (void)post:(NSString *)url param:(id)param constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))formData successBlock:(void (^)(ZNGBaseRequestResult *result))success failure:(void (^)(NSError *error))failure
{
    [self request:url method:HTTPMethodPOST param:param resultClass:[ZNGBaseRequestResult class] constructingBodyWithBlock:nil successBlock:success failure:failure];
}
+ (void)get:(NSString *)url param:(id)param constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))formData successBlock:(void (^)(ZNGBaseRequestResult *result))success failure:(void (^)(NSError *error))failure
{
    [self request:url method:HTTPMethodGET param:param resultClass:[ZNGBaseRequestResult class] constructingBodyWithBlock:nil successBlock:success failure:failure];
}

+ (void)post:(NSString *)url param:(id)param resultClass:(Class)resultClass constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))formData successBlock:(void (^)(id result))success failure:(void (^)(NSError *error))failure
{
    [self request:url method:HTTPMethodPOST param:param resultClass:resultClass constructingBodyWithBlock:formData successBlock:success failure:failure];
}

+ (void)get:(NSString *)url param:(id)param resultClass:(Class)resultClass constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))formData successBlock:(void (^)(id result))success failure:(void (^)(NSError *error))failure
{
    [self request:url method:HTTPMethodGET param:param resultClass:resultClass constructingBodyWithBlock:formData successBlock:success failure:failure];
}
@end


@implementation ZNGBaseRequestResult

@end

